package cn.ilikes.tools.hbase.jpa.metadatas.processor.processores;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import javax.persistence.Column;
import javax.persistence.Id;

import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.annotations.IndexColumn;
import cn.ilikes.tools.hbase.jpa.annotations.Save;
import cn.ilikes.tools.hbase.jpa.metadatas.EntityMetaDataImpl;
import cn.ilikes.tools.hbase.jpa.metadatas.IEntityMetaData;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.EntityFields;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.EntityFieldsImpl;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.IndexField;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.JPAFieldImpl;
import cn.ilikes.tools.hbase.jpa.metadatas.processor.TableProcessor;
import cn.ilikes.tools.hbase.jpa.metadatas.processor.validators.EntityFieldValidator;
import cn.ilikes.tools.hbase.jpa.metadatas.processor.validators.EntityValidatorException;
import cn.ilikes.tools.logs.Loggerfactory;

public class EntityFieldElementProcessors extends ElementProcessors implements Processors {

	private static Logger logger = Loggerfactory.instance(EntityFieldElementProcessors.class);

	private EntityFieldValidator entityFieldValidator = new EntityFieldValidator();

	private OneToOneRelationProcessor oneToOneRelationProcessor = new OneToOneRelationProcessor();

	private OneToManyRelationProcessor oneToManyRelationProcessor = new OneToManyRelationProcessor();

	private ManyToOneRelationProcessor manyToOneRelationProcessor = new ManyToOneRelationProcessor();

	@Override
	public void validators(Class<?> clazz, IEntityMetaData entityMetaData) throws EntityValidatorException {
		if (Loggerfactory.isdebug(logger))
			logger.debug("start  validators   entity   table field    ");
		try {
			entityFieldValidator.entityValidator(clazz, entityMetaData);
			oneToOneRelationProcessor.validators(clazz, entityMetaData);
			oneToManyRelationProcessor.validators(clazz, entityMetaData);
			manyToOneRelationProcessor.validators(clazz, entityMetaData);
		} catch (EntityValidatorException e) {
			throw new EntityValidatorException(e);
		}
	}

	@Override
	public void processors(Class<?> clazz, IEntityMetaData metadata) throws ElementProcessorException {
		if (Loggerfactory.isdebug(logger))
			logger.debug("start  processors   entity   table field    ");
		validators(clazz, metadata);
		EntityMetaDataImpl entityMetaDataImpl = entityMetaData(metadata);
		Field[] fs = clazz.getDeclaredFields();
		for (Field f : fs) {
			String fieldName = f.getName();
			if (fieldName.startsWith("serialVersionUID"))
				continue;
			EntityFieldsImpl entityFields = (EntityFieldsImpl) entityMetaDataImpl.getEntityField(fieldName);
			if (entityFields == null) {
				entityFields = new EntityFieldsImpl(EntityFields.EntityFieldsType.RealocalKey);
				entityMetaDataImpl.getEntityFields().put(fieldName, entityFields);
			}
			entityFields.setField(f);
			entityFields.setFieldName(fieldName);
			////////////////////////////////////////////////////////////////////////////////////////////////////////
			GetSettMethod(clazz,entityFields,f);
//			try {
//				// 获得和属性对应的getXXX()方法的名字
//				String firstLetter = fieldName.substring(0, 1).toUpperCase();
//				String getMethodName = "get" + firstLetter + fieldName.substring(1);
//				// 获得和属性对应的setXXX()方法的名字
//				String setMethodName = "set" + firstLetter + fieldName.substring(1);
//
//				// 获得和属性对应的getXXX()方法
//				Method getMethod = clazz.getMethod(getMethodName, new Class[] {});
//				// 获得和属性对应的setXXX()方法，使用filed对象的类型
//				Method setMethod = clazz.getMethod(setMethodName, new Class[] { f.getType() });
//
//				entityFields.setGetMethod(getMethod);
//
//				entityFields.setSetMethod(setMethod);
//
//			} catch (NoSuchMethodException e) {
//				Loggerfactory.error(logger, e);
//			} catch (SecurityException e) {
//				Loggerfactory.error(logger, e);
//			}

			/////////////////////////////////////////////////////////////////////////////////////////////////////////

			Column column = f.getAnnotation(Column.class);
			if (column != null) {
				TableProcessor.processorsIndexColumn(entityFields, f);
				processorsJPAColumn(entityFields, f);
			}

			Save save = f.getAnnotation(Save.class);
			if (save == null) {
				entityFields.setSave(true);
			} else {
				entityFields.setSave(save.save());
			}

			Id id = f.getAnnotation(Id.class);
			if (id != null) {
				EntityFieldsImpl entityFieldsId = new EntityFieldsImpl(EntityFields.EntityFieldsType.RealocalKey);
				entityFieldsId.setField(f);
				GetSettMethod(clazz,entityFieldsId,f);
				entityMetaDataImpl.setEntityFieldsId(entityFieldsId);
				
			}

		}

		oneToOneRelationProcessor.processors(clazz, entityMetaDataImpl);
		oneToManyRelationProcessor.processors(clazz, entityMetaDataImpl);
		manyToOneRelationProcessor.processors(clazz, entityMetaDataImpl);
	}

	//	private void processorsIndexColumn(EntityFieldsImpl entityFields, Field f) {
	//		IndexColumn indexColumn = f.getAnnotation(IndexColumn.class);
	//		if (indexColumn == null)
	//			return;
	//		IndexField indexField = new IndexField();
	//		indexField.setName((indexColumn.name().isEmpty() ? f.getName() : indexColumn.name()));
	//		indexField.setIndex(indexColumn.index());
	//		indexField.setBoost(indexColumn.boost());
	//		indexField.setStore(indexColumn.store());
	//		indexField.setTermVector(indexColumn.termvector());
	//		entityFields.setIndexField(indexField);
	//
	//	}

	private void processorsJPAColumn(EntityFieldsImpl entityFields, Field f) {

		Column column = f.getAnnotation(Column.class);
		if (column == null)
			return;
		JPAFieldImpl indexField = new JPAFieldImpl();
		String columnName = column.name();
		columnName = ((columnName == null || columnName.isEmpty()) ? f.getName() : columnName);
		indexField.setColumnName(columnName);
		entityFields.setjPAField(indexField);

		if (Loggerfactory.isdebug(logger))
			logger.debug("start processors  jpa  column ; " + columnName + "  field :   " + f.getName());

	}
	
	private void GetSettMethod(Class<?> clazz,EntityFieldsImpl entityFields,Field field ) throws ElementProcessorException
	{
		String fieldName = field.getName();
		try {
			// 获得和属性对应的getXXX()方法的名字
			String firstLetter = fieldName.substring(0, 1).toUpperCase();
			String getMethodName = "get" + firstLetter + fieldName.substring(1);
			// 获得和属性对应的setXXX()方法的名字
			String setMethodName = "set" + firstLetter + fieldName.substring(1);

			// 获得和属性对应的getXXX()方法
			Method getMethod = clazz.getMethod(getMethodName, new Class[] {});
			// 获得和属性对应的setXXX()方法，使用filed对象的类型
			Method setMethod = clazz.getMethod(setMethodName, new Class[] { field.getType() });

			entityFields.setGetMethod(getMethod);

			entityFields.setSetMethod(setMethod);

		} catch (NoSuchMethodException e) {
			Loggerfactory.error(logger, e);
			throw new ElementProcessorException(e);
		} catch (SecurityException e) {
			Loggerfactory.error(logger, e);
			throw new ElementProcessorException(e);
		}
	}

}
